---
id: worklets
sidebar_label: Worklets
sidebar_position: 1
---

# Worklets

Worklets are short-running JavaScript functions that can run on the [UI thread](/docs/fundamentals/glossary#ui-thread). Reanimated uses worklets to calculate view styles and react to events on the UI thread.

You can create your own worklets using the `'worklet';` directive at the top of a function.

```javascript
function myWorklet() {
  'worklet';
  console.log('Hello from a worklet');
}
```

The [Reanimated Babel Plugin](https://github.com/software-mansion/react-native-reanimated/blob/main/packages/react-native-worklets/plugin/README-dev.md#basics) looks for functions marked with the `'worklet'` directive and converts them into serializable objects. We call this process [workletization](/docs/fundamentals/glossary#to-workletize). These objects can then be copied and run over on the UI thread.

Most of the time when working with Reanimated and [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/) the code is automatically workletized and run on the UI thread by default.

```javascript
import { useAnimatedStyle } from 'react-native-reanimated';

function App() {
  const style = useAnimatedStyle(() => {
    // Running on the UI thread
    return { opacity: 0.5 };
  });
}
```

Functions marked with `'worklet';` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet';` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread).

You can use [`runOnUI`](https://docs.swmansion.com/react-native-worklets/docs/threading/runOnUI) to manually schedule worklet execution on the UI thread:

```javascript
function myWorklet() {
  'worklet';
  console.log('Hello from the UI thread');
}

function onPress() {
  runOnUI(myWorklet)();
}
```

You can pass arguments to worklets.

```javascript
function myWorklet(greeting) {
  'worklet';
  console.log(`${greeting} from the UI thread`);
}

function onPress() {
  runOnUI(myWorklet)('Howdy');
}
```

Worklets are [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). They can access variables declared outside of their own scope. Only variables referenced in the worklet body will be captured inside the worklet scope.

```javascript
const width = 135.5;

function otherWorklet() {
  'worklet';
  console.log('Captured width is', width);
}
```

Capturing large JavaScript objects inside of a worklet can lead to performance issues.

```javascript
const theme = {...}; // theme is a large object

function myWorklet() {
  'worklet';
  console.log(theme.color); // 🚨 referenced `color` but captured the whole `theme` object
}
```

You can get around this problem by first assigning the prop you want to use to a separate variable.

```javascript
const theme = {...};
const color = theme.color;

function myWorklet() {
  'worklet';
  console.log(color); // ✅ captured only `color`
}
```

Worklets can return data within the same thread.

```javascript
function returningWorklet() {
  'worklet';
  return "I'm back"; // on the UI thread
}

function someWorklet() {
  'worklet';
  const what = returningWorklet(); // still on the UI thread
  console.log('On the UI thread, other worklet says', what);
}
```

To pass data between UI and JS thread we use [shared values](/docs/fundamentals/glossary#shared-value).

```javascript
import { useSharedValue } from 'react-native-reanimated';

function App() {
  const width = useSharedValue(100);

  function myWorklet() {
    'worklet';
    width.value += 50;
  }

  useEffect(() => {
    console.log(width.value); // available on both JS and UI thread
  }, []);
}
```

You can run functions on the JS thread from the UI thread with [`runOnJS`](https://docs.swmansion.com/react-native-worklets/docs/threading/runOnJS). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state.

```javascript
import { router } from 'expo-router';
import { Gesture } from 'react-native-gesture-handler';

function App() {
  const tap = Gesture.Tap().onEnd(() => {
    // i'm a worklet too!
    // highlight-next-line
    runOnJS(router.back)();
  });
}
```

Functions passed to `runOnJS` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI thread](/docs/fundamentals/glossary#ui-thread):

```javascript
function App() {
  const tap = Gesture.Tap().onEnd(() => {
    // myFunction is defined on the UI thread 🚨
    const myFunction = () => {};
    runOnJS(myFunction)(); // 💥
  });
}
```

Worklets can run in other runtimes than the one provided by Reanimated. For example [VisionCamera](https://github.com/mrousavy/react-native-vision-camera) and [LiveMarkdown](https://github.com/Expensify/react-native-live-markdown) create their own worklet runtimes.

You can create your own worklet runtimes with [`createWorkletRuntime`](https://docs.swmansion.com/react-native-worklets/docs/threading/createWorkletRuntime) function.
